<?php

namespace Boosen\Company\app\Console\Commands;

use Illuminate\Console\Command;

use Boosen\Company\app\Models\CNBaseProductUrl;
use Boosen\Company\app\Models\CNProductUrl;

class CNProductUrlSpider extends Command
{
    const PAGE_SIZE = 1;

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'cn:product_url {start_id?}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $startId = $this->argument('start_id') ?: 1;
        $page = 1;

        while (true) {
            $baseUrls = CNBaseProductUrl::where('id', '>=', $startId)->simplePaginate(self::PAGE_SIZE, ['*'], 'page', $page);

            $break = (bool)!(count($baseUrls->items()) > 0);
            foreach ($baseUrls->items() as $item) {
                $this->info($item->url . ' start...');
                $break = !$this->processUrl($item);

                if ($break) break;

                $this->info('---- ' . $item->id . 'th done-----');
                if ($item->id % 2) {
                    sleep(2); 
                }
            }

            if ($break) break;
            $page++;

            sleep(3);
        }
    }


    private function processUrl($item)
    {
        $page = 1;
        $goutte = GoutteClient::getInstance();
        while (true) {
            $url = str_replace('1.html', $page . '.html', $item->url);
            $this->info($page . 'th start ....');
            // for proxy using
            while (true) {
                try {
                    $client = $goutte->client();
                    $crawler = $client->request('GET', $url);
                    $proCon = $crawler->filterXPath('//div[@class="pros-line"]/ul/li/dl/dt/a');
                    
                    if ($proCon->count() > 0) {

                        $proCon->each(function($node, $i) use ($item) {
                            CNProductUrl::updateOrCreate(['url' => $node->link()->getUri()], [
                                'base_url_id' => $item->id
                            ]);

                            $this->info('insert new url for ' . $item->company->name);
                        });

                        break; // will go to next page
                    } else {
                        return true;
                    }
                } catch (\Exception $e) {
                    $this->info($e->getMessage());

                    if ($crawler->filterXPath('//div[@class="warn_cont"]')->count()) {
                        $gutte->changeProxy();
                        $this->info('proxy change to ' . $gutte->getProxy());
                    } else {
                        // insert error message to DB

                        return false;
                    }
                    
                    if (false !== strposa($e->getMessage(), array('time out', 'timed out', 'reset', 'aborted', 'refused'))) {
                        if ($gutte->hasProxy()) {
                            $gutte->unsetProxy();
                        }

                        if ($gutte->proxyCount() == 0) {
                            $this->info('no useful proxy ');
                            sleep(10);
                        }
                    }
                }
            }

            $page++;
        }

    }

    private function processPage($url)
    {
        
    }
}
